import 'dart:async';
import 'package:flutter/foundation.dart';
import '../log/log.dart';

import 'timer_extends.dart';

///Completer 扩展方法
extension CUCompleterExtends<T> on Completer<T> {
  void cancel() {
    try {
      if (!isCompleted) {
        completeError(CancelException('Task cancelled'));
      }
    } catch (e) {}
  }
}

class CancelException implements Exception {
  final String message;

  CancelException(this.message);

  String toString() => "CancelException: $message";
}

/// CancellationToken 用于管理取消操作
class CancellationToken {
  bool _isCancelled = false;

  bool get isCancelled => _isCancelled;

  void cancel() {
    _isCancelled = true;
  }
}

class TimerCompleter {
  Timer? timer;
  Completer completer;

  TimerCompleter(this.timer, this.completer);

  void cancel() {
    timer?.cancel();
    completer.cancel();
  }
}

/// Future 扩展方法
extension CUFutureExtends<T> on Future<T> {
  Future<T> withCancel(CancellationToken cancellationToken) {
    return then((value) {
      if (cancellationToken.isCancelled) {
        throw CancelException("Task cancelled");
      }
      return value;
    }).catchError((error) {
      if (cancellationToken.isCancelled) {
        // throw CancelException("Task cancelled");
      }
      throw error;
    });
  }
}

typedef FutureFun<T> = Future<T> Function();
typedef FutureFunJob<T> = Future<T> Function(Job);

class Job {
  final Completer _completer;
  final CancellationToken _cancellationToken = CancellationToken();

  Job([Completer? completer]) : _completer = completer ?? Completer();

  get isCancel => _cancellationToken.isCancelled;

  get isActive => !isCancel && !isCompleted;

  Completer get completer => _completer;

  Future get future => _completer.future;

  bool get isCompleted => _completer.isCompleted;

  void cancel() {
    if (!isCompleted) {
      _cancellationToken.cancel();
      _completer.cancel();
    }
  }

  /// 任意 await 语句前检查取消标记
  Future<T> withCancel<T>(Future<T> future) async {
    return await future.withCancel(_cancellationToken);
  }

  //只有使用这个方法延迟才能被取消后续代码执行
  Future<void> delay(int delay) {
    return withCancel(delayFuture(delay));
  }

  Future catchError(Function onError, {bool Function(Object error)? test}) {
    future.catchError(onError);
    return future;
  }

  /// 多任务执行，方法带回调[Job]
  Future<List<T>> futureWait<T>(Iterable<FutureFun<T>> functions) {
    return Future.wait(functions.map((f) {
      return f();
    }));
  }

  /// 多任务执行，方法带回调[Job]
  Future<List<T>> futureWaitJob<T>(Iterable<FutureFunJob<T>> functions) {
    return Future.wait(functions.map((f) {
      return f(this);
    }));
  }
}

//作用域
class CoroutineScope {
  final Set<Job> _tasks = {};
  final Set<Timer> _timers = {};
  final CancellationToken _cancellationToken = CancellationToken();

  //协程崩溃回调
  static void Function(dynamic e, dynamic s)? onErrorCall;

  bool get isCancel => _cancellationToken.isCancelled;

  /// 多任务执行，方法带回调[CoroutineScope]
  Future<List<void>> futureWait(List<Function> functions) {
    return Future.wait(functions.map((f) {
      if (f is Function(CoroutineScope)) {
        return f(this);
      }
      return f();
    }));
  }

  /// 定时器,周期性执行
  Timer timerPeriodic(int milliseconds, Function(CoroutineScope, Timer) task, [Function? onError]) {
    final timer = Timer.periodic(Duration(milliseconds: milliseconds), (timer) {
      try {
        task(this, timer);
      } catch (e, s) {
        if (e is! CancelException) {
          LogUtils.e("", error: e, stackTrace: s);
          onErrorCall?.call(e, s);
        }
        if (onError != null) {
          if (onError is dynamic Function(Object, StackTrace)) {
            onError(e, s);
          } else if (onError is dynamic Function(Object)) {
            onError(e);
          } else {
            onError();
          }
        }
      }
    });
    _timers.add(timer);
    return timer;
  }

  Job launchS(Future Function(CoroutineScope) task, [Function? onError]) {
    return launch((s, j) => task(s), onError);
  }

  Job launchJ(Future Function(Job) task, [Function? onError]) {
    return launch((s, j) => task(j), onError);
  }

  Job launch(Future Function(CoroutineScope, Job) task, [Function? onError]) {
    final job = Job(Completer());
    _tasks.add(job);

    Future wrappedTask() async {
      try {
        await task(this, job);
        job.completer.complete();
      } catch (e, s) {
        if (!job.isCompleted) {
          job.completer.completeError(e, s);
        }
      } finally {
        _tasks.remove(job);
      }
    }

    wrappedTask();
    //这里需要捕获异常，否则会抛出异常
    job.future.catchError((e, s) {
      if (e is! CancelException) {
        LogUtils.e("", error: e, stackTrace: s);
        onErrorCall?.call(e, s);
      }
      if (onError != null) {
        if (onError is dynamic Function(Object, StackTrace)) {
          onError(e, s);
        } else if (onError is dynamic Function(Object)) {
          onError(e);
        } else {
          onError();
        }
      }
    });
    return job;
  }

  void cancel() {
    for (final job in _tasks) {
      if (!job.isCompleted) {
        job.cancel();
      }
    }
    for (final timer in _timers) {
      timer.cancel();
    }
    _cancellationToken.cancel();
    _tasks.clear();
    _timers.clear();
  }

  ///取消并且返回一个新的[CoroutineScope]
  CoroutineScope cancelNew() {
    cancel();
    return CoroutineScope();
  }

  /// 任意 await 语句前检查取消标记
  Future<T> withCancel<T>(Future<T> future) {
    return future.withCancel(_cancellationToken);
  }

  //只有使用这个方法延迟才能被取消后续代码执行
  Future<void> delay(int delay) {
    return withCancel(delayFuture(delay));
  }
}

///启动一个异步任务，并返回一个Completer对象，用于取消任务。
Job launch<T>(Future<T> Function(CoroutineScope) task, [Function? onError]) {
  return CoroutineScope().launch((scope, job) async {
    try {
      await task(scope);
    } catch (e, s) {
      if (onError != null) {
        if (onError is dynamic Function(Object, StackTrace)) {
          onError(e, s);
        } else if (onError is dynamic Function(Object)) {
          onError(e);
        } else {
          onError();
        }
      }
    }
  });
}

///启动一个异步任务，并返回一个Completer对象，用于取消任务。
Job launchSJ<T>(Future<T> Function(CoroutineScope, Job) task, [Function? onError]) {
  return CoroutineScope().launch((scope, job) async {
    try {
      await task(scope, job);
    } catch (e, s) {
      if (onError != null) {
        if (onError is dynamic Function(Object, StackTrace)) {
          onError(e, s);
        } else if (onError is dynamic Function(Object)) {
          onError(e);
        } else {
          onError();
        }
      }
    }
  });
}

///启动一个异步任务，并返回一个Completer对象，用于取消任务。
Job launchJ<T>(Future<T> Function(Job) task, [Function? onError]) {
  return CoroutineScope().launch((scope, job) async {
    try {
      await task(job);
    } catch (e, s) {
      if (onError != null) {
        if (onError is dynamic Function(Object, StackTrace)) {
          onError(e, s);
        } else if (onError is dynamic Function(Object)) {
          onError(e);
        } else {
          onError();
        }
      }
    }
  });
}

// 假设 R 是返回类型
/// Flutter compute和isolates 都是开启新的线程，但是内存不共享，导致单例不可用
Future<R> computeRun<R>(Future<R> Function() fun) {
  return compute(computeProxyFun, () {
    return fun();
  });
}

// 注意: computeProxyFun 不再是泛型方法，并且它是同步的。
R computeProxyFun<R>(R Function() fun) {
  // 如果 fun 执行的操作是异步的，那么你需要在这里使用 await，
  // 但 computeProxyFun 本身必须保持同步并返回实际值。
  return fun();
}

void main() async {
  print(DateTime.now().millisecond);
  print(DateTime.now().millisecondsSinceEpoch);
  Future aaa(Job job) async {
    await delayFuture(4000);
  }

  final task = launchSJ((scope, job) async {
    print("111111111111 run");
    // await job.withCancel(delayFuture(4000));
    await job.withCancel(aaa(job));
    print("111111111111");
  }, (e, s) {
    print("111111111 catchError2 ${e},,,${s}");
  });

  taskLaunch(() async {
    print("222222222 run");
    await delayFuture(2000);
    print("222222222");
    task.cancel();
  });
  taskLaunch(() async {
    print("3333333333 run");
    await delayFuture(6000);
    print("3333333333");
  });
  print('End');
}
